package icasue.tools.compile.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import icasue.reflect.annotations.NotNull;
import icasue.reflect.annotations.Nullable;
import icasue.reflect.handles.map.MapOF;
import lombok.Data;
import icasue.reflect.exceptions.TypeParseException;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2020/11/30 上午10:19
 * @UpdateDate:
 * @Description:
 */
public class JsonReaderUtil {

    public static <T> ReaderEntity readJson(String jsonFile,Class<T> target){
        String jsonString = readFile(jsonFile);
        return parseJsonSource(jsonString,target);
    }

    public static <T> T readJSON(String jsonResource,Class<T> type){
        String jsonString = readFile(jsonResource);
        try {
            return JSON.parseObject(jsonString,type);
        }catch (Throwable e){
            throw new TypeParseException("Json parse exception.",e);
        }
    }

    public static <T> List<T> readJSONAry(String jsonResource, Class<T> itemType){
        String jsonString = readFile(jsonResource);
        try {
            return JSON.parseArray(jsonString,itemType);
        }catch (Throwable e){
            throw new TypeParseException("JsonAry parse exception.",e);
        }
    }

    private static <T> ReaderEntity parseJsonSource(String jsonSource,Class<T> target){
        try {
            if(JSON.isValid(jsonSource)){
                ReaderEntity readerEntity = new ReaderEntity();
                Map map = JSON.parseObject(jsonSource, Map.class);
                Object metadata = MapOF.get_.apply(new Object[]{map,"metadata"});
                Object data = MapOF.get_.apply(new Object[]{map,"data"});
                if(metadata != null){
                    readerEntity.metadata = JSON.parseObject(JSON.toJSONString(metadata), ReaderEntity.HandleMetadata.class);
                }
                if(data != null){
                    if(Collection.class.isAssignableFrom(data.getClass())
                            || JSONArray.class.isAssignableFrom(data.getClass())) {
                        readerEntity.data = JSON.parseArray(JSON.toJSONString(data), target);
                    }else {
                        readerEntity.data = JSON.parseObject(JSON.toJSONString(data), target);
                    }
                }
                return readerEntity;
            }
            throw new TypeParseException("Json parse exception, type not support.");
        }catch (Throwable e){
            throw (RuntimeException)e;
        }
    }

    private static String readFile(String jsonFile){
        if(jsonFile == null){
            throw new RuntimeException("Can't read a 'null' classpath resource.");
        }
        InputStream parkStyleStream = null;
        try {
            parkStyleStream = JsonReaderUtil.class.getClassLoader().getResourceAsStream(jsonFile);
            BufferedReader streamReader = new BufferedReader(new InputStreamReader(parkStyleStream, "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null) {
                responseStrBuilder.append(inputStr);
            }
            return responseStrBuilder.toString();
        }catch (Throwable e){ } finally {
            synchronized (JsonReaderUtil.class) {
                if (parkStyleStream != null) {
                    try {
                        parkStyleStream.close();
                    } catch (IOException e) { }
                }
            }
        }
        return "";
    }

    public static String readStream(InputStream inStream){
        InputStream parkStyleStream = inStream;
        try {
            BufferedReader streamReader = new BufferedReader(new InputStreamReader(parkStyleStream, "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null) {
                responseStrBuilder.append(inputStr).append("\n");
            }
            return responseStrBuilder.toString();
        }catch (Throwable e){ } finally {
            synchronized (JsonReaderUtil.class) {
                if (parkStyleStream != null) {
                    try {
                        parkStyleStream.close();
                    } catch (IOException e) { }
                }
            }
        }
        return "";
    }


    @Data
    public static class ReaderEntity implements Serializable{
        public HandleMetadata metadata;
        public Object data;

        @Data
        public static class HandleMetadata{
            //方法描述
            @Nullable
            String functionDescription;
            //调度对象类名
            @NotNull
            String className;
            //调度的方法名
            @NotNull
            String methodName;
            //形参表列以及参数值
            @Nullable
            ArrayList<InvokerParams> params;
            @Data
            public static class InvokerParams{
                String paramDoc;
                String paramClassName;
                Object paramValue;
            }
        }
    }


}
